#pragma once

#include<iostream>
#include<queue>
#include<mutex>
#include<pthread.h>
#include "lockGuard.hpp"

const int gDefaultCap=5;
template <class T>
class BlockQueue
{
private:
    bool isQueueEmpty()
    {
        return _bq.size()==0;
    }
    bool isQueueFull()
    {
        return _bq.size()==0;
    }
public:
    BlockQueue(int capcity=gDefaultCap)
    :_capacity(_capacity)
    {
        pthread_mutex_init(&mutex,nullptr);
        pthread_cond_init(&_Empty,nullptr);
        pthread_cond_init(&_Full,nullptr);
    }
    void push(const T& in)
    {
        lockGuard lockguard(&mutex);
        while(isQueueFull())
        {
            pthread_cond_wait(&_Full,&mutex);
        }
        _bq.push(in);
        pthread_cond_signal(&_Empty);
    }
    void pop(T* out)
    {
        lockGuard lockguard(&_mutex);
        while(isQueueEmpty())
        {
            pthread_cond_wait(&_Empty,&_mutex);
        }
        *out=_bq.pop();
        pthread_cond_signal(&_Full);
    }
    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(_Empty);
        pthread_cond_destroy(_Full);
    }
private:
    queue<T> _bq;
    int _capacity;
    pthread_mutex_t _mutex;
    pthread_cond_t _Empty;
    pthread_cond_t _Full;
};
